home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / umich / network / ka9q / ka9q_src.arc / AX25.C < prev    next >
C/C++ Source or Header  |  1988-07-28  |  9KB  |  339 lines

  1. /* Low level AX.25 frame processing - address header */
  2.  
  3. #include <stdio.h>
  4. #include "global.h"
  5. #include "mbuf.h"
  6. #include "iface.h"
  7. #include "timer.h"
  8. #include "arp.h"
  9. #include "slip.h"
  10. #include "ax25.h"
  11. #include "lapb.h"
  12. #include <ctype.h>
  13.  
  14. /* AX.25 broadcast address: "QST-0" in shifted ascii */
  15. struct ax25_addr ax25_bdcst = {
  16.     'Q'<<1, 'S'<<1, 'T'<<1, ' '<<1, ' '<<1, ' '<<1,
  17.     ('0'<<1) | E,
  18. };
  19. char axbdcst[AXALEN];    /* Same thing, network format */
  20. struct ax25_addr mycall;
  21. int digipeat = 1;    /* Controls digipeating */
  22.  
  23. int digisent = 0;    /* DG2KK: counts frames to be digipeated */
  24. /* Send IP datagrams across an AX.25 link */
  25. int
  26. ax_send(bp,interface,gateway,precedence,delay,throughput,reliability)
  27. struct mbuf *bp;
  28. struct interface *interface;
  29. int32 gateway;
  30. char precedence;
  31. char delay;
  32. char throughput;
  33. char reliability;
  34. {
  35.     char *hw_addr,*res_arp();
  36.     struct ax25_cb *axp,*find_ax25(),*open_ax25();
  37.     struct ax25 addr;
  38.     struct ax25_addr destaddr;
  39.     struct mbuf *tbp;
  40.     extern int16 axwindow;
  41.     void ax_incom();
  42.     int16 size,bsize,seq;
  43.  
  44.     if((hw_addr = res_arp(interface,ARP_AX25,gateway,bp)) == NULLCHAR)
  45.         return;    /* Wait for address resolution */
  46.  
  47.     if(delay || (!reliability && (interface->flags == DATAGRAM_MODE))){
  48.         /* Use UI frame */
  49.         (*interface->output)(interface,hw_addr,
  50.             interface->hwaddr,PID_FIRST|PID_LAST|PID_IP,bp);
  51.         return;
  52.     }
  53.     /* Reliability is needed; use I-frames in AX.25 connection */
  54.     memcpy(destaddr.call,hw_addr,ALEN);
  55.     destaddr.ssid = hw_addr[ALEN];
  56.  
  57.     if((axp = find_ax25(&destaddr)) == NULLAX25 || axp->state != CONNECTED){
  58.         /* Open a new connection or reinitialize the old one */
  59.         atohax25(&addr,hw_addr,(struct ax25_addr *)interface->hwaddr);
  60.         axp = open_ax25(&addr,axwindow,ax_incom,NULLVFP,NULLVFP,interface,(char *)0);
  61.         if(axp == NULLAX25){
  62.             free_p(bp);
  63.             return;
  64.         }
  65.     }
  66.     /* If datagram is too big for one frame, send all but the last with
  67.      * the extension PID. Note: the copy to a new buf is necessary because
  68.      * AX.25 may continue retransmitting the frame after a local TCB has
  69.      * gone away, and using the buf directly would cause heap garbage to be
  70.      * transmitted. Besides, nobody would ever use AX.25 anywhere
  71.      * high performance is needed anyway...
  72.      */
  73.     bsize = len_mbuf(bp);
  74.     seq = 0;
  75.     while(bsize != 0){
  76.         size = min(bsize,axp->paclen);
  77.         /* Allocate buffer, allowing space for PID */
  78.         if((tbp = alloc_mbuf(size + 1)) == NULLBUF)
  79.             break;        /* out of memory! */
  80.         *tbp->data = PID_IP;
  81.         if(seq++ == 0)
  82.             *tbp->data |= PID_FIRST;     /* First in sequence */
  83.         if(size == bsize)
  84.             *tbp->data |= PID_LAST;        /* That's all of it */
  85.         /* else more to follow */
  86.  
  87.         tbp->cnt = 1;
  88.         tbp->cnt += pullup(&bp,tbp->data + 1,size);
  89.         send_ax25(axp,tbp);
  90.         bsize -= size;
  91.     }
  92.     free_p(bp);    /* Shouldn't be necessary */
  93. }
  94. /* Add AX.25 link header and send packet.
  95.  * Note that the calling order here must match ec_output
  96.  * since ARP also uses it.
  97.  */
  98. ax_output(interface,dest,source,pid,bp)
  99. struct interface *interface;
  100. char *dest;        /* Destination AX.25 address (7 bytes, shifted) */
  101.             /* Also includes digipeater string */
  102. char *source;        /* Source AX.25 address (7 bytes, shifted) */
  103. char pid;        /* Protocol ID */
  104. struct mbuf *bp;    /* Data field (follows PID) */
  105. {
  106.     struct mbuf *abp,*cbp,*htonax25();
  107.     struct ax25 addr;
  108.     
  109.     atohax25(&addr,dest,(struct ax25_addr *)source);
  110.     if((abp = htonax25(&addr)) == NULLBUF){
  111.         free_p(bp);
  112.         return;
  113.     }
  114.     /* Allocate mbuf for control and PID fields, and fill in */
  115.     if((cbp = alloc_mbuf((int16)2)) == NULLBUF){
  116.         free_p(abp);
  117.         free_p(bp);
  118.         return;
  119.     }
  120.     cbp->data[0] = UI;
  121.     cbp->data[1] = pid;
  122.     cbp->cnt = 2;
  123.  
  124.     /* Link everything together and ship it */
  125.     abp->next = cbp;
  126.     cbp->next = bp;
  127.     (*interface->raw)(interface,abp);
  128. }
  129. /* Process incoming AX.25 packets.
  130.  * After optional tracing, the address field is examined. If it is
  131.  * directed to us as a digipeater, repeat it.  If it is addressed to
  132.  * us or to QST-0, kick it upstairs depending on the protocol ID.
  133.  */
  134. int
  135. ax_recv(interface,bp)
  136. struct interface *interface;
  137. struct mbuf *bp;
  138. {
  139.     void ip_route(),arp_input();
  140.     struct ax25_addr *ap;
  141.     struct mbuf *htonax25(),*hbp;
  142.     char multicast = 0;
  143.     char nrnodes = 0;        /* DG2KK */
  144.     char control;
  145.     struct ax25 hdr;
  146.     struct ax25_cb *axp,*find_ax25(),*cr_ax25();
  147.     struct ax25_addr ifcall;
  148.     extern struct ax25_addr nr_nodebc;
  149.  
  150.     /* we need to use the call for this interface */
  151.     memcpy(ifcall.call,interface->hwaddr,ALEN);
  152.     ifcall.ssid = interface->hwaddr[ALEN];
  153.  
  154.     /* Pull header off packet and convert to host structure */
  155.     if(ntohax25(&hdr,&bp) < 0){
  156.         /* Something wrong with the header */
  157.         free_p(bp);
  158.         return;
  159.     }
  160.     /* Scan, looking for our call in the repeater fields, if any.
  161.      * Repeat appropriate packets.
  162.      */
  163.     for(ap = &hdr.digis[0]; ap < &hdr.digis[hdr.ndigis]; ap++){
  164.         if(ap->ssid & REPEATED)
  165.             continue;    /* Already repeated */
  166.         /* Count frames to be digipeated, even if digipeat is off
  167.          * (DG2KK)
  168.          */
  169.         if (addreq(ap,&mycall))
  170.             digisent++;
  171.         /* Check if packet is directed to us as a digipeater */
  172.         if(digipeat && addreq(ap,&mycall)){
  173.             /* Yes, kick it back out */
  174.             ap->ssid |= REPEATED;
  175.             if((hbp = htonax25(&hdr)) != NULLBUF){
  176.                 hbp->next = bp;
  177.                 if(interface->forw != NULLIF)
  178.                     (*interface->forw->raw)(interface->forw,hbp);
  179.                 else
  180.                     (*interface->raw)(interface,hbp);
  181.                 bp = NULLBUF;
  182.             }
  183.         }
  184.         free_p(bp);    /* Dispose if not forwarded */
  185.         return;
  186.     }
  187.     /* Packet has passed all repeaters, now look at destination */
  188.     if(addreq(&hdr.dest,&ax25_bdcst)){
  189.         multicast = 1;    /* Broadcast packet */
  190.     } else if(addreq(&hdr.dest,&mycall)){    /* DG2KK: was: &ifcall */
  191.         multicast = 0;    /* Packet directed at us */
  192.     } else if(addreq(&hdr.dest,&nr_nodebc)) {
  193.         nrnodes = 1;
  194.     } else {
  195.         /* Not for us */
  196.         free_p(bp);
  197.         return;
  198.     }
  199.     if(bp == NULLBUF){
  200.         /* Nothing left */
  201.         return;
  202.     }
  203.     /* Sneak a peek at the control field. This kludge is necessary because
  204.      * AX.25 lacks a proper protocol ID field between the address and LAPB
  205.      * sublayers; a control value of UI indicates that LAPB is to be
  206.      * bypassed.
  207.      */
  208.     control = *bp->data & ~PF;
  209.     if(control == UI){
  210.         char pid;
  211.  
  212.         (void) pullchar(&bp);
  213.         if(pullup(&bp,&pid,1) != 1)
  214.             return;        /* No PID */
  215.         /* DG2KK: new from netrom version */
  216.         if (nrnodes) {
  217.             if ((pid & (PID_FIRST | PID_LAST | PID_PID)) ==
  218.                 (PID_NETROM | PID_FIRST | PID_LAST))
  219.                 nr_nodercv(interface,&hdr.source,bp);
  220.             else    /* regular UI packets to "nodes" aren't for us */
  221.                 free_p(bp);
  222.             return;
  223.         }
  224.         else {
  225.         /* Handle packets. Multi-frame messages are not allowed */
  226.         switch(pid & (PID_FIRST | PID_LAST | PID_PID)){
  227.         case (PID_IP | PID_FIRST | PID_LAST):
  228.             ip_route(bp,multicast);
  229.             break;
  230.         case (PID_ARP | PID_FIRST | PID_LAST):
  231.             arp_input(interface,bp);
  232.             break;
  233.         default:
  234.             free_p(bp);
  235.             break;
  236.         }
  237.         return;
  238.         }
  239.     }
  240.  
  241.     /* If the packet was an I packet not directed to us,
  242.      * we should drop it here (shouldn't we, Phil?)
  243.      */
  244.     if (nrnodes || multicast) {
  245.         free_p(bp);
  246.         return;
  247.     }
  248.  
  249.     /* Find the source address in hash table */
  250.     if((axp = find_ax25(&hdr.source)) == NULLAX25){
  251.         /* Create a new ax25 entry for this guy,
  252.          * insert into hash table keyed on his address,
  253.          * and initialize table entries
  254.          */
  255.         if((axp = cr_ax25(&hdr.source)) == NULLAX25){
  256.             free_p(bp);
  257.             return;
  258.         }
  259.         axp->interface = interface;
  260.         /* Swap source and destination, reverse digi string */
  261.         ASSIGN(axp->addr.dest,hdr.source);
  262.         ASSIGN(axp->addr.source,hdr.dest);
  263.         if(hdr.ndigis > 0){
  264.             int i,j;
  265.  
  266.             /* Construct reverse digipeater path */
  267.             for(i=hdr.ndigis-1,j=0;i >= 0;i--,j++){
  268.                 ASSIGN(axp->addr.digis[j],hdr.digis[i]);
  269.                 axp->addr.digis[j].ssid &= ~(E|REPEATED);
  270.             }
  271.             /* Scale timers to account for extra delay */
  272.             axp->t1.start *= hdr.ndigis+1;
  273.             axp->t2.start *= hdr.ndigis+1;
  274.             axp->t3.start *= hdr.ndigis+1;
  275.         }
  276.         axp->addr.ndigis = hdr.ndigis;
  277.     }
  278.     if(hdr.cmdrsp == UNKNOWN)
  279.         axp->proto = V1;    /* Old protocol in use */
  280.     else
  281.         axp->proto = V2;
  282.  
  283.     lapb_input(axp,hdr.cmdrsp,bp);
  284. }
  285.  
  286. /* General purpose AX.25 frame output */
  287. sendframe(axp,cmdrsp,ctl,bp)
  288. struct ax25_cb *axp;
  289. char cmdrsp;
  290. char ctl;
  291. struct mbuf *bp;
  292. {
  293.     struct mbuf *hbp,*cbp,*htonax25();
  294.  
  295.     if(axp == NULL){
  296.         printf("NULL AXP!!\n");
  297.         return;
  298.     }
  299.     if(axp->interface == NULLIF){